<?php
namespace app\controller;

use app\BaseController;
use think\App;
use think\cache\driver\Memcached;
use think\facade\Db;

/**
 * Class Rank
 * @package app\controller
 *  redis 实现排行榜的功能
 */
class MemCache extends BaseController
{
    private $redis;
    private $rank;
    const PREFIX = 'rank:';
    public function __construct(App $app)
    {
        $this->mem = new Memcached();
        $this->rank = 'rank';

        parent::__construct($app);
    }

    // 初始化
    public function init(){
        $this->mem->set("key","刘老师可是可是");
        $s = $this->mem->get('key');
        echo $s;
    }
    ///获取初级排行榜
    public function rank(){
        $sort = input("sort")?'asc':'desc'; //
        $number = 20;
        $withscores =  true; //是否需要分数
        if ($sort == 'desc') {
            //desc  降序排列
            $rank =  $this->redis->zRevRange($this->rank, 0, $number -1, $withscores);//按照高分数顺序排行;
        } else {
            //asc  升序排列
            $rank =  $this->redis->zRange($this->rank, 0, $number -1, $withscores);//按照低分数顺序排行;
        }
        $this->zincrby();
        echo "<pre>";
        print_r($rank);
    }

    // 给某个成员加分
    function zincrby(){
        $score = mt_rand(0,10000);
        $member = '王五'.$score;
        $this->redis->zincrby($this->rank,$score*3,$member);
    }

    // 返回某个人的排名   从大到小排列  zrevrank   从小到达分数排列 zrank
    function getSomebodyRank(){
        $member = '王五'.mt_rand(0,10000);
        #$member = '王五0';
        $sbScore = $this->redis->zscore($this->rank,$member);
        $sbRank = $this->redis->zrevrank($this->rank,$member);
        echo $member.'分数为：'.$sbScore.',排名为：'.$sbRank;
    }

    protected function getOneDayRankings($date, $start, $stop) {
        $key = self::PREFIX . $date;
        return $this->redis->zRevRange($key, $start, $stop, true);
    }


    protected function getMultiDaysRankings($dates, $outKey, $start, $stop) {
        $keys = array_map(function($date) {
            return self::PREFIX . $date;
        }, $dates);

        $weights = array_fill(0, count($keys), 1);
        $this->redis->zUnion($outKey, $keys, $weights);
        return $this->redis->zRevRange($outKey, $start, $stop, true);
    }


    public function getYesterdayTop10() {
        $date = Carbon::now()->subDays(1)->format('Ymd');
        return $this->getOneDayRankings($date, 0, 9);
    }


    public static function getCurrentMonthDates() {
        $dt = Carbon::now();
        $days = $dt->daysInMonth;

        $dates = array();
        for ($day = 1; $day <= $days; $day++) {
            $dt->day = $day;
            $dates[] = $dt->format('Ymd');
        }
        return $dates;
    }


    public function getCurrentMonthTop10() {
        $dates = self::getCurrentMonthDates();
        return $this->getMultiDaysRankings($dates, 'rank:current_month', 0, 9);
    }
}
